#include "udp_server.h"

// udp不需要发送缓冲区，不需要对已发送的数据负责(超时重传)

udp_server::udp_server(int _port): port(_port)
{
}

void udp_server::init_server()
{
	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if(sock < 0) {	
		std::cerr << "socket create error" << std::endl;
		return;
	}

	struct sockaddr_in local;
	local.sin_family = AF_INET;
	local.sin_port = htons(port);
	// INADDR_ANY 当数据来的时候再绑定
	local.sin_addr.s_addr = htonl(INADDR_ANY);

	if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0) {
		std::cerr << "bind error" << std::endl;
		return;
	}
}

void udp_server::recv_data(std::string& out_string)
{
	char buff[BUFF_SIZE];

	struct sockaddr_in peer;
	socklen_t len = sizeof(peer);
	ssize_t s = recvfrom(sock, buff, BUFF_SIZE, 0, (struct sockaddr*)&peer, &len);
	
	// 收到数据
	if(s > 0) {
		buff[s] = 0;
		out_string = buff;
		pool.put_message(out_string);

		// 收到一条消息，将用户添加到map
		online.insert(std::pair<uint32_t, struct sockaddr_in>(peer.sin_addr.s_addr, peer));
	} else {
		std::cerr << "recv error" << std::endl;
	}

}

void udp_server::send_data(const std::string& in_string, const struct sockaddr_in &peer/*, const socklen_t &len*/)
{
	// 通过传参对端信息来保证有目标发送
	// 要发送的数据是 char* 所以要用c_str;
	sendto(sock, in_string.c_str(), in_string.size(), 0, (struct sockaddr*)&peer, sizeof(peer));
}

void udp_server::broadcast()
{
	std::string message;
	pool.get_message(message);

	std::map<uint32_t, struct sockaddr_in>::iterator iter = online.begin();

	for(; iter != online.end(); ++iter) {
		send_data(message, iter->second);
	}
	
}


udp_server::~udp_server()
{
	close(sock);
	port = -1;
}
